/*
 *  Copyright (c) 2011, Apexes Network Technology. All rights reserved.
 * 
 *       http://www.apexes.net
 * 
 */
package com.cooltool.component;

import java.awt.*;
import java.awt.event.*;
import javax.swing.DefaultButtonModel;
import javax.swing.ImageIcon;
import javax.swing.JFormattedTextField;
import javax.swing.SwingConstants;

/**
 * 支持图标的 JTextField 组件。可选择将图标放置在最左侧或最右侧，或者左右两侧都放置。
 * 
 * @author HeDYn<hedyn@foxmail.com>
 * @version 0.1.20110222
 */
public class JImageTextField extends JFormattedTextField {
	private static final long serialVersionUID = -1268251675925527935L;
    
    private static final int DEFAULT_CLOUMN_COUNT = 10;
	
	/** 设置的图像 */
    private ImageIcon               leftIcon = null;
    private ImageIcon               rightIcon = null;
    
    private Dimension originalPreferredSize;

    private DefaultButtonModel      leftActionModel;
    private DefaultButtonModel      rightActionModel;

    private String                  toolTipText;
    private String                  leftToolTipText;
    private String                  rightToolTipText;

    public JImageTextField() {
        this(null, DEFAULT_CLOUMN_COUNT, null, null);
    }

    public JImageTextField(String text) {
        this(text, DEFAULT_CLOUMN_COUNT);
    }

    public JImageTextField(int columns) {
        this(null, columns, null, null);
    }

    public JImageTextField(String text, int columns) {
        this(text, columns, null, null);
    }

    public JImageTextField(ImageIcon leftIcon, ImageIcon rightIcon) {
        this(null, DEFAULT_CLOUMN_COUNT, leftIcon, rightIcon);
    }

    public JImageTextField(String text, int columns,
            ImageIcon leftIcon, ImageIcon rightIcon) {
        super(text);
        setColumns(columns);
        originalPreferredSize = getPreferredSize();
        initListener();
        this.leftIcon = leftIcon;
        this.rightIcon = rightIcon;
        if (leftIcon != null || rightIcon != null) {
            calculatePreferredSize();
        }
    }

    public JImageTextField(AbstractFormatterFactory factory) {
        this(factory, DEFAULT_CLOUMN_COUNT);
        originalPreferredSize = getPreferredSize();
        initListener();
    }
    
    public JImageTextField(AbstractFormatterFactory factory, int columns) {
        super(factory);
        setColumns(columns);
        originalPreferredSize = getPreferredSize();
        initListener();
    }

    public JImageTextField(AbstractFormatterFactory factory, Object text,
            int columns, ImageIcon leftIcon, ImageIcon rightIcon) {
        this(factory);
        setColumns(columns);
        originalPreferredSize = getPreferredSize();
        this.leftIcon = leftIcon;
        this.rightIcon = rightIcon;
        if (leftIcon != null || rightIcon != null) {
            calculatePreferredSize();
        }
    }

    private void initListener() {
        leftActionModel = new DefaultButtonModel() {
			@Override
            protected void fireActionPerformed(ActionEvent e) {
                e.setSource(JImageTextField.this);
                super.fireActionPerformed(e);
            }
        };
        rightActionModel = new DefaultButtonModel() {
			@Override
            protected void fireActionPerformed(ActionEvent e) {
                e.setSource(JImageTextField.this);
                super.fireActionPerformed(e);
            }
        };
        this.setToolTipText(notifyAction);
        addMouseMotionListener(new MouseMotionAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                int i = getPosition(e.getPoint());
                switch (i) {
                    case SwingConstants.CENTER:
                        leftActionModel.setArmed(false);
                        rightActionModel.setArmed(false);
                        setCursor(new Cursor(Cursor.TEXT_CURSOR));
                        setToolTipText(toolTipText);
                        break;
                    case SwingConstants.LEFT:
                        setCursor(Cursor.getDefaultCursor());
                        setToolTipText(leftToolTipText);
                        break;
                    case SwingConstants.RIGHT:
                        setCursor(Cursor.getDefaultCursor());
                        setToolTipText(rightToolTipText);
                }
            }
        });
        addMouseListener(new MouseAdapter() {
            @Override
            public void mouseExited(MouseEvent e) {
                leftActionModel.setArmed(false);
                rightActionModel.setArmed(false);
            }
            @Override
            public void mousePressed(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    int i = getPosition(e.getPoint());
                    switch (i) {
                        case SwingConstants.LEFT:
                            leftActionModel.setArmed(true);
                            leftActionModel.setPressed(true);
                            break;
                        case SwingConstants.RIGHT:
                            rightActionModel.setArmed(true);
                            rightActionModel.setPressed(true);
                            break;
                    }
                }
            }

            @Override
            public void mouseReleased(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    int i = getPosition(e.getPoint());
                    switch (i) {
                        case SwingConstants.LEFT:
                            rightActionModel.setArmed(false);
                            leftActionModel.setPressed(false);
                            break;
                        case SwingConstants.RIGHT:
                            leftActionModel.setArmed(false);
                            rightActionModel.setPressed(false);
                            break;
                    }
                }
            }
        });
    }

    /**
     * 获取指定的坐标在组件中的位置
     *
     * @param point
     *          坐标
     * @return
     *          返回值为以下之一：
     *          SwingConstants.LEFT - 左侧，
     *          SwingConstants.RIGHT - 右侧，
     *          SwingConstants.CENTER - 中间
     */
    public int getPosition(Point point) {
        Insets insets = getInsets();
        int left = insets.left;
        int right = getWidth() - insets.right;
        if (leftIcon != null && point.x <= left) {
            return SwingConstants.LEFT;
        }
        if (rightIcon != null && point.x >= right) {
            return SwingConstants.RIGHT;
        }
        return SwingConstants.CENTER;
    }

    /**
     * 设置左侧的图标
     *
     * @param icon
     *          放置到左侧的图标对象，如果为 null 则表示左侧不放置图标
     */
    public void setLeftIcon(ImageIcon icon) {
        leftIcon = icon;
        calculatePreferredSize();
    }

    /**
     * 设置右侧的图标
     * 
     * @param icon
     *          放置到右侧的图标对象，如果为 null 则表示右侧不放置图标
     */
    public void setRightIcon(ImageIcon icon) {
        rightIcon = icon;
        calculatePreferredSize();
    }

    private void calculatePreferredSize() {
        Dimension size = new Dimension(originalPreferredSize);
        Insets insets = getInsets();
        int left = 0;
        int right = 0;
        size.width -= insets.left + insets.right;
        if (leftIcon != null) {
            left = leftIcon.getIconWidth() + 8;
            size.width += left;
            size.height = Math.max(size.height, leftIcon.getIconHeight());
        }
        if (rightIcon != null) {
            right = rightIcon.getIconWidth();
            size.width += right;
            size.height = Math.max(size.height, rightIcon.getIconHeight());
        }
        size.width += insets.left + insets.right;
        setMargin(new Insets(0, left, 0, right));
        super.setPreferredSize(size);
    }

    public String getLeftToolTipText() {
        return leftToolTipText;
    }

    public void setLeftToolTipText(String text) {
        leftToolTipText = text;
    }

    public String getRightToolTipText() {
        return rightToolTipText;
    }

    public void setRightToolTipText(String text) {
        rightToolTipText = text;
    }

    /**
     * 添加一个点击左侧图标所触发的事件的监听
     * 
     * @param l
     */
    public void addLeftActionListener(ActionListener l) {
        leftActionModel.addActionListener(l);
    }

    /**
     * 移除指定的点击左侧图标所触发的事件的监听
     *
     * @param l
     */
    public void removeLeftActionListener(ActionListener l) {
        leftActionModel.removeActionListener(l);
    }

    /**
     * 添加一个点击右侧图标所触发的事件的监听
     *
     * @param l
     */
    public void addRightActionListener(ActionListener l) {
        rightActionModel.addActionListener(l);
    }

    /**
     * 移除指定的点击右侧图标所触发的事件的监听
     *
     * @param l
     */
    public void removeRightActionListener(ActionListener l) {
        rightActionModel.removeActionListener(l);
    }

    @Override
    public void setPreferredSize(Dimension preferredSize) {
        super.setPreferredSize(preferredSize);
        originalPreferredSize = preferredSize;
    }

    @Override
    public void setEnabled(boolean enabled) {
        super.setEnabled(enabled);
        leftActionModel.setEnabled(enabled);
        rightActionModel.setEnabled(enabled);
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        Graphics2D g2d = (Graphics2D)g.create();
        Insets insets = getInsets();
        Insets margin = getMargin();
        int h = getHeight() - insets.top - insets.bottom;
        int left = 0;
        int right = 0;
        if (margin != null) {
            left = margin.left;
            right = margin.right;
        }
        if (rightIcon != null) {
            int x = getWidth() - insets.right - rightIcon.getIconWidth() + right;
            int y = (h - rightIcon.getIconHeight()) / 2 + insets.top;
            g2d.drawImage(rightIcon.getImage(), x, y, this);
        }
        if (leftIcon != null) {
            int x = insets.left - left;
            int y = (h - leftIcon.getIconHeight()) / 2 + insets.top;
            g2d.drawImage(leftIcon.getImage(), x, y, this);
            
            g2d.setColor(Color.lightGray);
            x = insets.left - 4;
            g2d.drawLine(x, y + 2, x, getHeight()- insets.bottom - 2);
        }
        g2d.dispose();
    }
}
